#ifndef _GRID_H_
#define _GRID_H_

#include <string>
#include <algorithm>

#include "vec.hpp"

class Grid
{
public:
	typedef wchar_t Tile;

	Grid(int c = 0, int r = 0)
	{
		cols = 0;
		rows = 0;
		Resize(c, r);
	}

	~Grid()
	{
	}

	Grid(const Grid & src, const Box2i & region);

	int Cols() const
	{
		return cols;
	}

	int Rows() const
	{
		return rows;
	}

	int TileCt() const
	{
		return cols * rows;
	}

	int TileN(int c, int r) const
	{
		return (r * cols) + c;
	}

	int TileR(int i)
	{
		return i / cols;
	}

	int TileC(int i)
	{
		return i % cols;
	}

	Tile GetI(int i) const
	{
		return tiles[i];
	}

	void PutI(int i, Tile tile)
	{
		tiles[i] = tile;
	}

	Tile Get(int c, int r) const
	{
		return GetI(TileN(c, r));
	}

	void Put(int c, int r, Tile tile)
	{
		PutI(TileN(c, r), tile);
	}

	const Tile* Data() const
	{
		return tiles.data();
	}

	void Resize(int newcols, int newrows);

	void Clear(Tile tile = 0)
	{
		tiles.replace(0, TileCt(), TileCt(), tile);
	}

	void Clamp(int & c, int & r) const
	{
		c = std::max(0, std::min(c, cols - 1));
		r = std::max(0, std::min(r, rows - 1));
	}

	int Printf(int c, int r, const Tile *fmt, ...);

	int Replace(Tile find, Tile repl);

	int GPut(int c, int r, const Grid & grid);
	int GComp(int c, int r, const Grid & grid);
	int GReplace(const Grid & srch, const Grid & repl);

private:
	int cols, rows;
	std::basic_string<Tile> tiles;
};

#endif
